package com.yuanheng100.ems4j.service;

import com.riversoft.weixin.common.WxClient;
import com.riversoft.weixin.common.message.Media;
import com.riversoft.weixin.common.message.MsgType;
import com.riversoft.weixin.common.message.Text;
import com.riversoft.weixin.qy.QyWxClientFactory;
import com.riversoft.weixin.qy.base.CorpSetting;
import com.riversoft.weixin.qy.contact.Departments;
import com.riversoft.weixin.qy.contact.Tags;
import com.riversoft.weixin.qy.contact.Users;
import com.riversoft.weixin.qy.contact.department.Department;
import com.riversoft.weixin.qy.contact.tag.Tag;
import com.riversoft.weixin.qy.contact.tag.TagUsers;
import com.riversoft.weixin.qy.contact.tag.TagUsersResult;
import com.riversoft.weixin.qy.contact.user.*;
import com.riversoft.weixin.qy.message.Messages;
import com.riversoft.weixin.qy.message.json.ImageMessage;
import com.riversoft.weixin.qy.message.json.TextMessage;
import com.yuanheng100.ems4j.api.IWeChatService;
import com.yuanheng100.ems4j.common.constant.Gender;
import com.yuanheng100.ems4j.common.constant.MessageStatus;
import com.yuanheng100.ems4j.mapper.Ems4jWeChatMapper;
import com.yuanheng100.ems4j.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by jlqian on 2017/1/16.
 * 注：微信SDK来源于 创河软件 的开源项目： https://github.com/borball/weixin-sdk
 */
public class WeChatServiceImpl implements IWeChatService
{
    private static Logger logger = LoggerFactory.getLogger(WeChatServiceImpl.class);

    @Autowired
    private Ems4jWeChatMapper ems4jWeChatMapper;

    private WeChatEnv weChatEnv = null;

    public void setWeChatEnv(WeChatEnv weChatEnv)
    {
        this.weChatEnv = weChatEnv;
    }

    /**
     * 创建部门
     *
     * @param name     部门名称。长度限制为32个字（汉字或英文字母），字符不能包括\:*?"<>｜
     * @param parentId 父亲部门id。根部门id为1
     * @param order    在父部门中的次序值。order值小的排序靠前。
     * @param id       部门id，整型。指定时必须大于1，不指定时则自动生成
     */
    @Override
    public void createDepartment(String name, Integer parentId, Integer order, Integer id)
    {
        Departments departments = new Departments();
        departments.setWxClient(weChatEnv.getWxClient());

        Department department = new Department();
        department.setName(name);
        department.setParentId(parentId);
        if (order != null)
        {
            department.setOrder(order);
        }
        if (id != null)
        {
            department.setId(id);
        }
        departments.create(department);
    }

    /**
     * 更新部门
     *
     * @param id       部门id
     * @param name     部门名称。长度限制为32个字（汉字或英文字母），字符不能包括\:*?"<>｜
     * @param parentId 父亲部门id。根部门id为1
     * @param order    在父部门中的次序值。order值小的排序靠前。
     */
    @Override
    public void updateDepartment(Integer id, String name, Integer parentId, Integer order)
    {
        Departments departments = new Departments();
        departments.setWxClient(weChatEnv.getWxClient());

        Department department = new Department();
        department.setName(name);
        department.setParentId(parentId);
        if (order != null)
        {
            department.setOrder(order);
        }
        if (id != null)
        {
            department.setId(id);
        }
        departments.update(department);
    }

    /**
     * 删除部门
     *
     * @param id 部门id。（注：不能删除根部门；不能删除含有子部门、成员的部门）
     */
    @Override
    public void deleteDepartment(Integer id)
    {
        Departments departments = new Departments();
        departments.setWxClient(weChatEnv.getWxClient());
        departments.delete(id);
    }

    /**
     * 获取部门列表
     *
     * @param id 部门id。获取指定部门及其下的子部门
     */
    @Override
    public List<Ems4jDepartment> listDepartment(Integer id)
    {
        Departments departments = new Departments();
        departments.setWxClient(weChatEnv.getWxClient());
        List<Department> list = departments.list(id);
        ArrayList<Ems4jDepartment> ems4jDepartments = new ArrayList<Ems4jDepartment>();
        for (Department department : list)
        {
            ems4jDepartments.add(convertDepartment2Ems4jDepartment(department));
        }
        return ems4jDepartments;
    }

    /**
     * 创建标签
     *
     * @param tagname 标签名称，长度限制为32个字（汉字或英文字母），标签名不可与其他标签重名。
     * @param tagid   标签id，整型，指定此参数时新增的标签会生成对应的标签id，不指定时则以目前最大的id自增。
     */
    @Override
    public void createRole(String tagname, Integer tagid)
    {
        Tags tags = new Tags();
        tags.setWxClient(weChatEnv.getWxClient());
        Tag tag = new Tag(tagid, tagname);
        tags.create(tag);
    }

    /**
     * 更新标签名字
     *
     * @param tagid   标签ID
     * @param tagname 标签名称，长度限制为32个字（汉字或英文字母），标签不可与其他标签重名。
     */
    @Override
    public void updateRole(Integer tagid, String tagname)
    {
        Tags tags = new Tags();
        tags.setWxClient(weChatEnv.getWxClient());
        Tag tag = new Tag(tagid, tagname);
        tags.update(tag);
    }

    /**
     * 删除标签
     *
     * @param tagid 标签ID 注:标签的成员列表为空。
     */
    @Override
    public void deleteRole(Integer tagid)
    {
        Tags tags = new Tags();
        tags.setWxClient(weChatEnv.getWxClient());
        tags.delete(tagid);
    }

    /**
     * 获取标签列表
     */
    @Override
    public List<Ems4jRole> listRole()
    {
        Tags tags = new Tags();
        tags.setWxClient(weChatEnv.getWxClient());
        List<Tag> list = tags.list();
        ArrayList<Ems4jRole> ems4jRoles = new ArrayList<>();
        for (Tag tag : list)
        {
            ems4jRoles.add(convertTag2Ems4jRole(tag));
        }
        return ems4jRoles;
    }

    /**
     * 创建成员
     *
     * @param userId        成员UserID。对应管理端的帐号，企业内必须唯一。不区分大小写，长度为1~64个字节
     * @param name          成员名称。长度为1~64个字节
     * @param department    成员所属部门id列表,不超过20个
     * @param position      职位信息。长度为0~64个字节
     * @param mobile        手机号码。企业内必须唯一，mobile/weixinid/email三者不能同时为空
     * @param gender        性别。1表示男性，2表示女性
     * @param email         邮箱。长度为0~64个字节。企业内必须唯一
     * @param weixinId      微信号。企业内必须唯一。（注意：是微信号，不是微信的名字）
     * @param avatarMediaId 成员头像的mediaid，通过多媒体接口上传图片获得的mediaid
     * @param extAttr       扩展属性。扩展属性需要在WEB管理端创建后才生效，否则忽略未知属性的赋值
     */
    @Override
    public void createUser(String userId, String name, int[] department, String position, String mobile, Short gender, String email, String weixinId, String avatarMediaId, Map<String, String> extAttr)
    {
        Users users = new Users();
        users.setWxClient(weChatEnv.getWxClient());

        CreateUser createUser = new CreateUser();
        createUser.setUserId(userId);
        createUser.setName(name);
        createUser.setDepartment(department);
        createUser.setPosition(position);
        createUser.setMobile(mobile);
        if (gender != null)
        {
            if (gender.equals(Gender.MALE.code))
            {
                createUser.setGender(AbstractUser.Gender.MALE);
            } else if (gender.equals(Gender.FEMALE.code))
            {
                createUser.setGender(AbstractUser.Gender.FEMALE);
            } else
            {
                logger.error("成员性别有误！");
            }
        }
        createUser.setEmail(email);
        createUser.setWeixinId(weixinId);
        createUser.setAvatarMediaId(avatarMediaId);
        if (extAttr != null && !extAttr.isEmpty())
        {
            AbstractUser.ExtAttr extAttr1 = new AbstractUser.ExtAttr();
            ArrayList<AbstractUser.ExtAttr.Attr> attrs = new ArrayList<AbstractUser.ExtAttr.Attr>();
            for (Map.Entry<String, String> entry : extAttr.entrySet())
            {
                AbstractUser.ExtAttr.Attr attr = new AbstractUser.ExtAttr.Attr(entry.getKey(), entry.getValue());
                attrs.add(attr);
            }
            extAttr1.setAttrs(attrs);
            createUser.setExtAttr(extAttr1);
        }
        users.create(createUser);
    }

    /**
     * 更新成员
     *
     * @param userId        成员UserID。对应管理端的帐号，企业内必须唯一。不区分大小写，长度为1~64个字节
     * @param name          成员名称。长度为1~64个字节
     * @param department    成员所属部门id列表,不超过20个
     * @param position      职位信息。长度为0~64个字节
     * @param mobile        手机号码。企业内必须唯一，mobile/weixinid/email三者不能同时为空
     * @param gender        性别。1表示男性，2表示女性
     * @param email         邮箱。长度为0~64个字节。企业内必须唯一
     * @param weixinId      微信号。企业内必须唯一。（注意：是微信号，不是微信的名字）
     * @param enable        启用/禁用成员
     * @param avatarMediaId 成员头像的mediaid，通过多媒体接口上传图片获得的mediaid
     * @param extAttr       扩展属性。扩展属性需要在WEB管理端创建后才生效，否则忽略未知属性的赋值
     */
    @Override
    public void updateUser(String userId, String name, int[] department, String position, String mobile, Short gender, String email, String weixinId, Boolean enable, String avatarMediaId, Map<String, String> extAttr)
    {
        Users users = new Users();
        users.setWxClient(weChatEnv.getWxClient());

        UpdateUser updateUser = new UpdateUser();
        updateUser.setUserId(userId);
        updateUser.setName(name);
        updateUser.setDepartment(department);
        updateUser.setPosition(position);
        updateUser.setMobile(mobile);
        if (gender != null)
        {
            if (gender.equals(Gender.MALE.code))
            {
                updateUser.setGender(AbstractUser.Gender.MALE);
            } else if (gender.equals(Gender.FEMALE.code))
            {
                updateUser.setGender(AbstractUser.Gender.FEMALE);
            } else
            {
                logger.error("成员性别有误！");
            }
        }
        updateUser.setEmail(email);
        updateUser.setWeixinId(weixinId);
        if (enable != null)
        {
            updateUser.setEnable(enable);
        }
        updateUser.setAvatarMediaId(avatarMediaId);
        if (extAttr != null && !extAttr.isEmpty())
        {
            AbstractUser.ExtAttr extAttr1 = new AbstractUser.ExtAttr();
            ArrayList<AbstractUser.ExtAttr.Attr> attrs = new ArrayList<AbstractUser.ExtAttr.Attr>();
            for (Map.Entry<String, String> entry : extAttr.entrySet())
            {
                AbstractUser.ExtAttr.Attr attr = new AbstractUser.ExtAttr.Attr(entry.getKey(), entry.getValue());
                attrs.add(attr);
            }
            extAttr1.setAttrs(attrs);
            updateUser.setExtAttr(extAttr1);
        }
        users.update(updateUser);
    }

    /**
     * 删除成员
     *
     * @param userId 成员UserID。对应管理端的帐号，企业内必须唯一。不区分大小写，长度为1~64个字节
     */
    @Override
    public void deleteUser(String userId)
    {
        Users users = new Users();
        users.setWxClient(weChatEnv.getWxClient());

        users.delete(userId);
    }

    /**
     * 批量删除成员
     *
     * @param userIds 成员UserID列表。对应管理端的帐号。（最多支持200个）
     */
    @Override
    public void batchDeleteUser(List<String> userIds)
    {
        Users users = new Users();
        users.setWxClient(weChatEnv.getWxClient());

        users.delete(userIds);
    }

    /**
     * 获取成员
     *
     * @param userId 成员UserID。对应管理端的帐号
     * @return
     */
    @Override
    public Ems4jEmployee getUser(String userId)
    {
        Users users = new Users();
        users.setWxClient(weChatEnv.getWxClient());
        ReadUser readUser = users.get(userId);
        return convertSimpleUser2Ems4jEmployee(readUser);
    }

    /**
     * 获取部门成员
     *
     * @param departmentId 获取的部门id
     * @param fetchChild   是否递归获取子部门下面的成员
     * @return
     */
    @Override
    public List<Ems4jEmployee> getDepartmentUser(Integer departmentId, Boolean fetchChild)
    {
        Users users = new Users();
        users.setWxClient(weChatEnv.getWxClient());
        List<SimpleUser> simpleUsers = users.simpleList(departmentId, fetchChild, null);
        ArrayList<Ems4jEmployee> ems4jEmployees = new ArrayList<Ems4jEmployee>();
        for (SimpleUser simpleUser : simpleUsers)
        {
            ems4jEmployees.add(convertSimpleUser2Ems4jEmployee(simpleUser));
        }
        return ems4jEmployees;
    }

    /**
     * 获取部门成员(详情)
     *
     * @param departmentId 获取的部门id
     * @param fetchChild   是否递归获取子部门下面的成员
     * @return
     */
    @Override
    public List<Ems4jEmployee> getDepartmentUserDetails(Integer departmentId, Boolean fetchChild)
    {
        Users users = new Users();
        users.setWxClient(weChatEnv.getWxClient());
        List<ReadUser> list = users.list(departmentId, fetchChild, null);
        ArrayList<Ems4jEmployee> ems4jEmployees = new ArrayList<Ems4jEmployee>();
        for (ReadUser readUser : list)
        {
            ems4jEmployees.add(convertSimpleUser2Ems4jEmployee(readUser));
        }
        return ems4jEmployees;
    }

    /**
     * 获取标签成员
     *
     * @param tagid 标签ID
     * @return
     */
    @Override
    public List<Ems4jEmployee> getTagUser(Integer tagid)
    {
        Tags tags = new Tags();
        tags.setWxClient(weChatEnv.getWxClient());
        TagUsers tagUsers = tags.getUsers(tagid);
        List<SimpleUser> simpleUsers = tagUsers.getUsers();
        ArrayList<Ems4jEmployee> ems4jEmployees = new ArrayList<Ems4jEmployee>();
        for (SimpleUser simpleUser : simpleUsers)
        {
            ems4jEmployees.add(convertSimpleUser2Ems4jEmployee(simpleUser));
        }
        return ems4jEmployees;
    }

    /**
     * 增加标签成员
     *
     * @param tagid     标签ID
     * @param userlist  企业成员ID列表，注意：userlist、partylist不能同时为空，单次请求长度不超过1000
     * @param partylist 企业部门ID列表，注意：userlist、partylist不能同时为空，单次请求长度不超过100
     * @return
     */
    @Override
    public TagUsersResult addTagUser(Integer tagid, List<String> userlist, List<Integer> partylist)
    {
        Tags tags = new Tags();
        tags.setWxClient(weChatEnv.getWxClient());
        return tags.addUsers(tagid, userlist, partylist);
    }

    /**
     * 删除标签成员
     *
     * @param tagid     标签ID
     * @param userlist  企业成员ID列表，注意：userlist、partylist不能同时为空
     * @param partylist 企业部门ID列表，注意：userlist、partylist不能同时为空
     * @return
     */
    @Override
    public TagUsersResult delTagUser(Integer tagid, List<String> userlist, List<Integer> partylist)
    {
        Tags tags = new Tags();
        tags.setWxClient(weChatEnv.getWxClient());
        return tags.deleteUsers(tagid, userlist, partylist);
    }

    /**
     * 发送微信文本消息
     *
     * @param touser  成员ID列表（消息接收者，多个接收者用‘|’分隔，最多支持1000个）。特殊情况：指定为@all，则向关注该企业应用的全部成员发送
     * @param toparty 部门ID列表，多个接收者用‘|’分隔，最多支持100个。当touser为@all时忽略本参数
     * @param totag   标签ID列表，多个接收者用‘|’分隔，最多支持100个。当touser为@all时忽略本参数
     * @param agentid 企业应用的id，整型。可在应用的设置页面查看
     * @param safe    表示是否是保密消息，默认不保密
     * @param content 消息内容，最长不超过2048个字节，注意：主页型应用推送的文本消息在微信端最多只显示20个字（包含中英文）
     */
    @Override
    public void sendTextMsg(String touser, String toparty, String totag, Integer agentid, Boolean safe, String content)
    {
        Messages messages = new Messages();
        messages.setWxClient(weChatEnv.getWxClient());

        TextMessage textMessage = new TextMessage();
        textMessage.setText(new Text(content));
        textMessage.setToUser(touser);
        textMessage.setToParty(toparty);
        textMessage.setToTag(totag);
        textMessage.setAgentId(agentid);
        if (safe != null)
        {
            textMessage.setSafe(safe);
        }
        messages.send(textMessage);
        //持久化
        Ems4jWeChat ems4jWeChat = new Ems4jWeChat();
        ems4jWeChat.setTouser(touser);
        ems4jWeChat.setToparty(toparty);
        ems4jWeChat.setTotag(totag);
        ems4jWeChat.setSendTime(new Date());
        ems4jWeChat.setContent(content);
        ems4jWeChat.setMsgtype(MsgType.text.name().toUpperCase());
        ems4jWeChat.setResultCode(MessageStatus.SUCCESS.getCode());
        ems4jWeChatMapper.insert(ems4jWeChat);
    }

    @Override
    public void sendTextMsg(Ems4jWeChat ems4jWeChat)
    {

        Messages messages = new Messages();
        messages.setWxClient(weChatEnv.getWxClient());

        TextMessage textMessage = new TextMessage();
        textMessage.setText(new Text(ems4jWeChat.getContent()));
        textMessage.setToUser(ems4jWeChat.getTouser());
        textMessage.setToParty(ems4jWeChat.getToparty());
        textMessage.setToTag(ems4jWeChat.getTotag());
        textMessage.setAgentId(ems4jWeChat.getAgentid());
        messages.send(textMessage);

        ems4jWeChat.setSendTime(new Date());
        ems4jWeChat.setMsgtype(MsgType.text.name().toUpperCase());
        ems4jWeChat.setResultCode(MessageStatus.SUCCESS.getCode());
        ems4jWeChatMapper.insert(ems4jWeChat);
    }

    /**
     * 发送微信图片消息
     *
     * @param touser   成员ID列表（消息接收者，多个接收者用‘|’分隔，最多支持1000个）。特殊情况：指定为@all，则向关注该企业应用的全部成员发送
     * @param toparty  部门ID列表，多个接收者用‘|’分隔，最多支持100个。当touser为@all时忽略本参数
     * @param totag    标签ID列表，多个接收者用‘|’分隔，最多支持100个。当touser为@all时忽略本参数
     * @param agentid  企业应用的id，整型。可在应用的设置页面查看
     * @param safe     表示是否是保密消息，默认不保密
     * @param media_id 图片媒体文件id，可以调用上传临时素材或者永久素材接口获取,永久素材media_id必须由发消息的应用创建
     */
    @Override
    public void sendImageMsg(String touser, String toparty, String totag, Integer agentid, Boolean safe, String media_id)
    {
        Messages messages = new Messages();
        ImageMessage imageMessage = new ImageMessage();
        imageMessage.setToUser(touser);
        imageMessage.setToParty(toparty);
        imageMessage.setToTag(totag);
        imageMessage.setAgentId(agentid);
        if (safe != null)
        {
            imageMessage.setSafe(safe);
        }
        imageMessage.setMedia(new Media(media_id));
        messages.setWxClient(weChatEnv.getWxClient());
        messages.send(imageMessage);
        //持久化
        Ems4jWeChat ems4jWeChat = new Ems4jWeChat();
        ems4jWeChat.setTouser(touser);
        ems4jWeChat.setToparty(toparty);
        ems4jWeChat.setTotag(totag);
        ems4jWeChat.setSendTime(new Date());
        try
        {
            ems4jWeChat.setMedia_id(Integer.parseInt(media_id));
        } catch (NumberFormatException e)
        {
        }
        ems4jWeChat.setMsgtype(MsgType.image.name().toUpperCase());
        ems4jWeChat.setResultCode(MessageStatus.SUCCESS.getCode());
        ems4jWeChatMapper.insert(ems4jWeChat);
    }

    @Override
    public void sendImageMsg(Ems4jWeChat ems4jWeChat)
    {
        Messages messages = new Messages();
        ImageMessage imageMessage = new ImageMessage();
        imageMessage.setToUser(ems4jWeChat.getTouser());
        imageMessage.setToParty(ems4jWeChat.getToparty());
        imageMessage.setToTag(ems4jWeChat.getTotag());
        imageMessage.setAgentId(ems4jWeChat.getAgentid());
        imageMessage.setMedia(new Media(ems4jWeChat.getMedia_id().toString()));
        messages.setWxClient(weChatEnv.getWxClient());
        messages.send(imageMessage);

        ems4jWeChat.setSendTime(new Date());
        ems4jWeChat.setMsgtype(MsgType.image.name().toUpperCase());
        ems4jWeChat.setResultCode(MessageStatus.SUCCESS.getCode());
        ems4jWeChatMapper.insert(ems4jWeChat);
    }

    @Override
    public void getPage(Ems4jPage<Ems4jWeChat> page, Map<String, Object> conditions)
    {
        //查询总数
        Long total = ems4jWeChatMapper.selectCountByCondition(conditions);
        page.setTotalCount(total);

        //查询结果
        List<Ems4jWeChat> list = ems4jWeChatMapper.selectListByCondition(conditions, page);
        page.setResult(list);
    }

    private Ems4jRole convertTag2Ems4jRole(Tag tag)
    {
        Ems4jRole ems4jRole = new Ems4jRole();
        ems4jRole.setRoleid(tag.getId());
        ems4jRole.setRolename(tag.getName());
        return ems4jRole;
    }

    private Ems4jDepartment convertDepartment2Ems4jDepartment(Department department)
    {
        Ems4jDepartment ems4jDepartment = new Ems4jDepartment();
        ems4jDepartment.setId(department.getId());
        ems4jDepartment.setName(department.getName());
        ems4jDepartment.setParentid(department.getParentId());
        ems4jDepartment.setOrdernum(((Integer) department.getOrder()).shortValue());
        return ems4jDepartment;
    }

    private Ems4jEmployee convertSimpleUser2Ems4jEmployee(SimpleUser simpleUser)
    {
        Ems4jEmployee ems4jEmployee = new Ems4jEmployee();
        ems4jEmployee.setUserid(Integer.valueOf(simpleUser.getUserId()));
        ems4jEmployee.setName(simpleUser.getName());
        ems4jEmployee.setDepartment(simpleUser.getDepartment()[0]);

        if (simpleUser instanceof ReadUser)
        {
            ReadUser readUser = (ReadUser) simpleUser;
            ems4jEmployee.setMobile(Long.parseLong(readUser.getMobile()));
            ems4jEmployee.setEmail(readUser.getEmail());
            ems4jEmployee.setPosition(readUser.getPosition());
            ems4jEmployee.setWeixinid(readUser.getWeixinId());
        }
        return ems4jEmployee;
    }

    public class WeChatEnv
    {
        private WxClient wxClient;

        private String corpId;

        private String corpSecret;

        public WxClient getWxClient()
        {
            if (corpId == null || corpSecret == null)
            {
                throw new RuntimeException("微信环境参数不全");
            }
            if (wxClient == null)
            {
                CorpSetting corpSetting = new CorpSetting();
                corpSetting.setCorpId(corpId);
                corpSetting.setCorpSecret(corpSecret);
                wxClient = QyWxClientFactory.getInstance().with(corpSetting);
            }
            return wxClient;
        }

        public String getCorpId()
        {
            return corpId;
        }

        public void setCorpId(String corpId)
        {
            this.corpId = corpId;
        }

        public String getCorpSecret()
        {
            return corpSecret;
        }

        public void setCorpSecret(String corpSecret)
        {
            this.corpSecret = corpSecret;
        }
    }
}
